package net.tw.transactional2.config;

import org.springframework.boot.autoconfigure.task.TaskExecutionProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.Hashtable;
import java.util.concurrent.ThreadPoolExecutor;

public class Transactional2Config {

    @Bean(name = "threadExchangeTable")
    public Hashtable<Long, Object> threadExchangeTable() {
        return new Hashtable<>();
    }

    @Bean("taskExecutor")
    public ThreadPoolTaskExecutor getAsyncExecutor(TaskExecutionProperties taskExecutionProperties) {

        //设置线程池
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();

        //设置核心线程数，默认值为1
        executor.setCorePoolSize(taskExecutionProperties.getPool().getCoreSize());

        //设置允许的最大核心线程数，默认值为Integer.MAX_VALUE
        executor.setMaxPoolSize(taskExecutionProperties.getPool().getMaxSize());

        //允许空闲线程存活时间,默认值60秒
        executor.setKeepAliveSeconds((int) taskExecutionProperties.getPool().getKeepAlive().getSeconds());

        //缓冲队列数,默认Integer.MAX_VALUE
        executor.setQueueCapacity(0);

        //如果为真线程池会销毁0，否则销毁至至setCorePoolSize设定值或setMaxPoolSize设定值，默认值false
        executor.setAllowCoreThreadTimeOut(taskExecutionProperties.getPool().isAllowCoreThreadTimeout());

        //线程池名前缀
        executor.setThreadNamePrefix("transactional2-thread-");

        //当关闭服务时，是否等待所有线程执行完毕，默认为false， 不等待，线程会抛出终止异常
        //true:二次未提交的记录会自动提交至数据库
        //false:抛出终止异常系统会自动回滚
        executor.setWaitForTasksToCompleteOnShutdown(false);

        //如果setWaitForTasksToCompleteOnShutdown参数设置为true时使用，等待设置秒数后如还未关闭强制关闭服务（系统认为是安全关闭）
        executor.setAwaitTerminationSeconds((int) taskExecutionProperties.getShutdown().getAwaitTerminationPeriod().getSeconds());

        //ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常。 默认策略
        //ThreadPoolExecutor.DiscardPolicy：也是丢弃任务，但是不抛出异常。
        //ThreadPoolExecutor.DiscardOldestPolicy：丢弃队列最前面的任务，然后重新尝试执行任务（重复此过程）
        //ThreadPoolExecutor.CallerRunsPolicy：由调用线程处理该任务
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());

        //初始化线程池
        executor.initialize();

        //放入IOC容器
        return executor;
    }
}
